<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.14.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>DM-CtrlH7-BF-DevProgram: can_comm</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectlogo"><img alt="Logo" src="DMBF-Black.png"/></td>
  <td id="projectalign">
   <div id="projectname">DM-CtrlH7-BF-DevProgram<span id="projectnumber">&#160;beta 0.1</span>
   </div>
   <div id="projectbrief">C.ONE Studio Damiao Development Board Framework</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.14.0 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
$(function() { codefold.init(); });
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search',true);
  $(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(function(){initNavTree('md_modules_2can__comm_2can__comm.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>

<div><div class="header">
  <div class="headertitle"><div class="title">can_comm </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="autotoc_md40"></a></p>
<p align="right"></p>
<p><a href="#" onclick="location.href='mai'+'lto:'+'neo'+'zn'+'g1@'+'hn'+'u.e'+'du'+'.cn'; return false;">neozn<span class="obfuscator">.nosp@m.</span>g1@h<span class="obfuscator">.nosp@m.</span>nu.ed<span class="obfuscator">.nosp@m.</span>u.cn</a></p>
<blockquote class="doxtable">
<p>TODO:</p>
<ol type="1">
<li>对<span class="tt">CANCommGet()</span>进行修改，使得其可以返回数据是否更新的相关信息。 </li>
</ol>
</blockquote>
<h1 class="doxsection"><a class="anchor" id="autotoc_md41"></a>
重要提醒</h1>
<p>如果传输过程中出现多次丢包或长度校验不通过，尤其是传输长度较大的时候，请开启CAN的Auto Retransmission，并尝试修改CANComm实例的发送和接受ID（以提高在总线仲裁中的优先级）。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md42"></a>
总览和封装说明</h1>
<p>CAN comm是用于CAN多机通信的模块。你不需要关心实现的协议，**只需要传入你想发送/接收的结构体的长度**（通过<span class="tt">sizeof()</span>获取）即可。单帧发送长度目前限制为60字节，如果需要加长可以在<span class="tt"><a class="el" href="can__comm_8h.html" title="用于多机CAN通信的收发模块">can_comm.h</a></span>中修改<span class="tt">CAN_COMM_MAX_BUFFSIZE</span>的定义值。注意CAN的负载以及使用此模块的发送频率，否则可能造成堵塞。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md43"></a>
代码结构</h1>
<p>.h中放置的是数据定义和外部接口，以及协议的定义和宏，.c中包含一些私有函数。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md44"></a>
外部接口</h1>
<div class="fragment"><div class="line"><a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *CANCommInit(<a class="code hl_struct" href="struct_c_a_n_comm___init___config__s.html">CANComm_Init_Config_s</a>* comm_config);</div>
<div class="line"><span class="keywordtype">void</span> CANCommSend(<a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *instance, uint8_t *data);</div>
<div class="line"><span class="keywordtype">void</span> *CANCommGet(<a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *instance);</div>
<div class="line">uint8_t CANCommIsOnline(<a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *instance);</div>
<div class="ttc" id="astruct_c_a_n_comm___init___config__s_html"><div class="ttname"><a href="struct_c_a_n_comm___init___config__s.html">CANComm_Init_Config_s</a></div><div class="ttdef"><b>Definition</b> can_comm.h:49</div></div>
<div class="ttc" id="astruct_c_a_n_comm_instance_html"><div class="ttname"><a href="struct_c_a_n_comm_instance.html">CANCommInstance</a></div><div class="ttdef"><b>Definition</b> can_comm.h:27</div></div>
</div><!-- fragment --><p>第一个函数将会初始化一个CANComm实例，返回其指针。使用CANComm进行通信的应用应该保存返回的指针。初始化需要传入一个初始化结构体。请在应用初始化的时候调用该函数。推荐的结构体配置方式如下：</p>
<div class="fragment"><div class="line"><span class="comment">/* 初始化结构体的定义 */</span></div>
<div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line">    can_instance_config_s can_config;</div>
<div class="line">    uint8_t send_data_len; <span class="comment">//发送数据长度</span></div>
<div class="line">    uint8_t recv_data_len; <span class="comment">//接收数据长度,两者请用sizeof获取</span></div>
<div class="line">} <a class="code hl_struct" href="struct_c_a_n_comm___init___config__s.html">CANComm_Init_Config_s</a>;</div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_c_a_n_comm___init___config__s.html">CANComm_Init_Config_s</a> cconfig = {</div>
<div class="line">  .can_config = {</div>
<div class="line">            .can_handle=&amp;hcan1,</div>
<div class="line">            .tx_id=0x02,</div>
<div class="line">            .rx_id=0x03},</div>
<div class="line">  .send_data_len = <span class="keyword">sizeof</span>(your_data_structure),</div>
<div class="line">  .recv_data_len = <span class="keyword">sizeof</span>(recv_data_structure)</div>
<div class="line">};</div>
</div><!-- fragment --><p>第二个函数将会通过CAN发送一帧数据。这里的“帧”不是CAN的一帧报文，而是你使用的数据。在CANComm初始化的时候，使用sizeof获得你要发送的数据的长度。调用此函数时，将你的数据结构或数据cast成<span class="tt">u8</span>类型的指针传入即可。==**特别注意，你的结构体需要使用预编译指令<span class="tt">#pragma pack(1)</span>以及<span class="tt">#pragma pack()</span>包裹**==，从而进行字节压缩而不进行字节对齐，如：</p>
<div class="fragment"><div class="line"><span class="preprocessor">#pragma pack(1)</span></div>
<div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line">    uint8_t aa;</div>
<div class="line">    <span class="keywordtype">float</span> bb;</div>
<div class="line">    <span class="keywordtype">double</span> cc;</div>
<div class="line">    uint16_t dd;</div>
<div class="line">} some_struct;</div>
<div class="line"><span class="preprocessor">#pragma pack()</span></div>
</div><!-- fragment --><p>只有这样，这个结构体才不会进行padding扩充字节实现字节对齐。你可以尝试一下，如果不使用pack处理，上面的结构体将会占据18个字节以上的空间；开启pack后，会降低至15。更多关于字节对齐的内容，自行查询。</p>
<blockquote class="doxtable">
<p>后期可能更新字节对齐和内存访问相关的教程。 </p>
</blockquote>
<p><span class="tt">CANCommGet()</span>是获取来自CANComm接收到的数据的接口，返回值为一个void类型指针，你需要通过**强制类型转换**将其变为你设定的接收类型指针，然后就可以访问其数据了。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md45"></a>
私有函数和变量</h1>
<div class="fragment"><div class="line"><span class="keyword">static</span> <a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *can_comm_instance[MX_CAN_COMM_COUNT] = {NULL};</div>
<div class="line"><span class="keyword">static</span> uint8_t idx; </div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> CANCommResetRx(<a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a> *ins);</div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> CANCommRxCallback(can_instance *_instance);</div>
</div><!-- fragment --><p>第一个指针数组保存所有的can comm实例，从而在callback中区分不同实例。idx是初始化使用的索引，用于确定每个can comm实例指针存放的位置。</p>
<p><span class="tt">CANCommResetRx()</span>在<span class="tt">CANCommRxCallback()</span>中多次被调用，用于清空接收缓冲区。</p>
<p><span class="tt">CANCommRxCallback()</span>是CAN comm初始化can实例时的回调函数，用于can接收中断，进行协议解析。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md46"></a>
使用范例</h1>
<p>例如，这里要发送的数据是一个float，接收的数据是如下的<span class="tt">struct</span>，**==注意要使用pack==**：</p>
<div class="fragment"><div class="line"><span class="preprocessor">#pragma pack(1)</span></div>
<div class="line"><span class="keyword">struct </span>test</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">float</span> aa;</div>
<div class="line"> <span class="keywordtype">float</span> bb;</div>
<div class="line"> <span class="keywordtype">float</span> cc;</div>
<div class="line"> uint16_t dd;</div>
<div class="line">};</div>
<div class="line"><span class="preprocessor">#pragma pack()</span></div>
</div><!-- fragment --><p>初始化时设置如下：</p>
<div class="fragment"><div class="line"><a class="code hl_struct" href="struct_c_a_n_comm___init___config__s.html">CANComm_Init_Config_s</a> cconfig = {</div>
<div class="line">  .can_config = {</div>
<div class="line">            .can_handle=&amp;hcan1,</div>
<div class="line">            .tx_id=0x02,</div>
<div class="line">            .rx_id=0x03},</div>
<div class="line">  .send_data_len = <span class="keyword">sizeof</span>(float),</div>
<div class="line">  .recv_data_len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> test)</div>
<div class="line">};</div>
<div class="line"><a class="code hl_struct" href="struct_c_a_n_comm_instance.html">CANCommInstance</a>* ins = <a class="code hl_function" href="can__comm_8h.html#a611c266bef866f02414a73b7d5584f86">CANCommInit</a>(&amp;cconfig);</div>
<div class="ttc" id="acan__comm_8h_html_a611c266bef866f02414a73b7d5584f86"><div class="ttname"><a href="can__comm_8h.html#a611c266bef866f02414a73b7d5584f86">CANCommInit</a></div><div class="ttdeci">CANCommInstance * CANCommInit(CANComm_Init_Config_s *comm_config)</div><div class="ttdoc">初始化CANComm</div><div class="ttdef"><b>Definition</b> can_comm.c:80</div></div>
</div><!-- fragment --><p>通过<span class="tt">CANCommGet()</span>并使用强制类型转换获得接收到的数据指针：</p>
<div class="fragment"><div class="line"><span class="keyword">struct </span>test* data_ptr=(<span class="keyword">struct </span>test*)CANCommGet(ins)</div>
</div><!-- fragment --><p>发送通过<span class="tt">CANCommSend()</span>，建议使用强制类型转换：</p>
<div class="fragment"><div class="line"><span class="keywordtype">float</span> tx=114.514;</div>
<div class="line">CANCommSend(ins, (uint8_t*)&amp;tx);</div>
</div><!-- fragment --><h1 class="doxsection"><a class="anchor" id="autotoc_md47"></a>
接收解析流程</h1>
<p>CAN comm的通信协议如下：</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">帧头  </th><th class="markdownTableHeadNone">数据长度  </th><th class="markdownTableHeadNone">数据  </th><th class="markdownTableHeadNone">crc8校验  </th><th class="markdownTableHeadNone">帧尾  </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">'s'（0x73）  </td><td class="markdownTableBodyNone">0~255  </td><td class="markdownTableBodyNone">最大60（可修改）  </td><td class="markdownTableBodyNone">校验码  </td><td class="markdownTableBodyNone">'e'（0x65）  </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">1-byte  </td><td class="markdownTableBodyNone">1-byte  </td><td class="markdownTableBodyNone">n-byte  </td><td class="markdownTableBodyNone">1-byte  </td><td class="markdownTableBodyNone">1-byte  </td></tr>
</table>
<p>接收的流程见代码注释。</p>
<p>流程图如下：<img src="../../.assets/CANcomm.png" alt="未命名文件" class="inline"/> </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div id="page-nav" class="page-nav-panel">
<div id="page-nav-resize-handle"></div>
<div id="page-nav-tree">
<div id="page-nav-contents">
</div><!-- page-nav-contents -->
</div><!-- page-nav-tree -->
</div><!-- page-nav -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.14.0 </li>
  </ul>
</div>
</body>
</html>
